﻿#include<iostream>
#include<easyx.h>
#include<time.h>
#include"drawImge.h" //对PNG图处理输出的自定义函数使用，自定义头文件代码在最下面
using namespace std;

void outpicture() {
	// 定义图片变量    int a;
	IMAGE imgLandscape;
	// 加载图片    scanf("%d",&a);
	loadimage(&imgLandscape, "x64/landscape.jpg", 550, 450);
	//基于当前main.cpp在的目录，使用相对路径       400,200设置图片大小
	// 图片格式必须经过“画图”转成jpg，即使原图是jpg也需要
	putimage(0, 0, &imgLandscape);// 输出图片     cout<<a<<endl;

	//使用掩码图与原图实现透明贴图
	IMAGE imgTou[2];
	loadimage(imgTou, "x64/yanMaTu.jpg", 200, 200);
	loadimage(imgTou + 1, "x64/yuanTu.jpg", 200, 200);
	putimage(10, 10, imgTou, NOTSRCERASE);       //先绘制掩码图
	putimage(10, 10, imgTou + 1, SRCINVERT); // 再绘制原图        两个图位置要相同
	// NOTSRCERASE  和  SRCINVERT ：绘制模式，控制图像与屏幕的混合方式。

	//直接输出透明贴图 PNG
	IMAGE imgPNG;
	// 加载PNG图像（确保图像是带透明通道的PNG）
	loadimage(&imgPNG, "x64/PNG.png", 150, 100);
	// 使用自定义函数DrawImage绘制透明图
	drawImge(300, 200, imgPNG, 0.06);//0.06是自定义阈值
	/*
	===================== 透明处理阈值选用指南 =====================

【阈值的作用】
决定哪些像素被视为背景（将被透明化）：
- 亮度 < 阈值 ➔ 判定为背景
- 亮度 ≥ 阈值 ➔ 判定为前景

【推荐阈值范围】
| 背景类型            | 建议阈值 | 典型示例                | 注意事项                  |
|---------------------|----------|-------------------------|--------------------------|
| 纯黑色背景          | 0.03-0.05| RGB(0,0,0)             | 默认值0.03适用大多数情况 |
| 深灰色背景          | 0.05-0.10| RGB(30,30,30)          | 需防止前景阴影被误删     |
| 暗色非黑背景        | 0.06-0.15| RGB(10,20,5)           | 需结合色相判断           |
| 复杂/渐变背景       | 动态调整 | RGB(0,0,0)-RGB(50,50,50)| 可能需要分区域处理       |

【调试步骤】
1. 初始测试：使用默认阈值0.03观察效果
2. 存在问题：
   - 背景残留 ➔ 提高阈值（每次+0.02）
   - 前景缺失 ➔ 降低阈值（每次-0.01）
3. 精确调试：
   for (float t = 0.02; t <= 0.15; t += 0.01) {
	   transparentimage(x, y, img, t);
	   getch(); // 按键盘观察不同阈值效果
   }

【注意事项】
1. 测量背景亮度：
   使用取色工具获取背景区域的实际亮度值：
   - 在Photoshop/GIMP中查看亮度(L)值
   - 在代码中添加调试输出：
	 ```cpp
	 COLORREF bg_color = getimagepixel(&img, x, y);
	 float h, s, l;
	 RGBtoHSL(bg_color, &h, &s, &l);
	 printf("背景亮度：%.2f\n", l);
	 ```

2. 特殊场景处理：
   - 半透明边缘：阈值可设0.08-0.12 + 边缘羽化处理
   - 彩色背景：需结合色相判断（需修改代码）
	 （例如绿色背景：检查色相值是否在绿色范围）

【示例调试案例】
案例：背景为深蓝色（RGB(10, 10, 50)）
1. 转换为HSL：亮度 L ≈ 0.12
2. 初始阈值0.03 ➔ 背景未完全透明
3. 调整阈值至0.13 ➔ 背景完全透明
4. 验证前景：检查角色边缘是否被误删

【最佳实践】
1. 为不同素材建立阈值预设：
   ```cpp
   // 敌人素材（黑背景）
   #define THRESHOLD_ENEMY 0.03
   // 子弹素材（灰背景）
   #define THRESHOLD_BULLET 0.08
   // 特效素材（渐变背景）
   #define THRESHOLD_EFFECT 0.12

	*/

	// 多张PNG图片输出组成动画
	IMAGE imgCartoon[4];
	char path[100];
	for (int i = 0; i < 4; i++) {
		sprintf(path, "x64/cartonn%d.png", i);
		loadimage(imgCartoon + i, path, 50, 50);
	}
	int idx = 0;
	const clock_t FPS = 1000 / 60;
	clock_t starttime, endtime;
	int speed = 200;    // 每200ms切换一张动画
	while (true) {
		starttime = clock();
		BeginBatchDraw();
		cleardevice();
		drawImge(300, 300, imgCartoon[idx], 0.06);//使用定义函数，如果不是PNG图，只能两张图叠加实现动画
		EndBatchDraw();
		//idx = ++idx % 4;
		idx = (clock() / speed) % 4;  //实现每200ms切换一次动画
		endtime = clock() - starttime;
		if (FPS - endtime > 0) Sleep(FPS - endtime);
	}
	/*
1.帧率控制的作用
   60帧（约16.67ms/帧）的目的是稳定程序运行的节奏，避免循环无节制地占用CPU资源。它通过  Sleep(FPS - endtime)  让出空闲时间，降低CPU占用率，同时保证画面刷新的流畅性（即使内容未变化）。
2.动画切换速度的作用
   200ms切换图片是控制动画内容的更新频率，它决定了何时切换到下一张图。但这一操作本身不限制绘制频率，如果关闭帧率控制，循环可能以极高频率运行（如每秒上千次），导致无意义的重复绘制。
3.两者的协作关系
   无帧率控制时：画面会以最大速度刷新（如1000帧/秒），但内容每200ms才变化一次。这会导致大量冗余绘制，浪费资源。
	有帧率控制时：画面以稳定的60帧刷新，每帧绘制时检查是否需要更新内容（通过  clock() / speed ）。既避免了资源浪费，又让动画切换更精确。
	*/
}

int main() {
	initgraph(600, 450, 1);
	setbkcolor(WHITE);
	cleardevice();

	outpicture();

	getchar();
	closegraph();
	return 0;
}

/*

// drawImge
#pragma once
#ifndef __TRANSPARENT_IMAGE_H__
#define __TRANSPARENT_IMAGE_H__

#include <graphics.h>

// 透明图像处理函数
// 参数说明：
// x, y   : 绘制位置
// img    : 要处理的图像对象
// threshold : 亮度阈值（默认0.03，可自定义）
inline void drawImge(int x, int y,  const IMAGE& img, float threshold = 0.03) {
	IMAGE img1 = img; // 创建图像副本
	DWORD* d1 = GetImageBuffer(&img1);
	const int total_pixels = img1.getwidth() * img1.getheight();

	// 像素处理
	for (int i = 0; i < total_pixels; ++i) {
		float h, s, l;
		RGBtoHSL(BGR(d1[i]), &h, &s, &l);

		// 处理逻辑
		if (l < threshold) { // 低亮度区域设为白色
			d1[i] = BGR(WHITE);
		}
		else { // 其他区域设为黑色
			d1[i] = BGR(BLACK);
		}
	}

	// 双缓冲绘制
	putimage(x, y, &img1, SRCAND); // 先与背景做"与"操作
	putimage(x, y, &img, SRCPAINT); // 再与原图做"或"操作
}

#endif // __TRANSPARENT_IMAGE_H__

*/